home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
gnu
/
nethack.lha
/
nethack-3.1
/
win
/
X11
/
winmenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-01-18
|
10KB
|
399 lines
/* SCCS Id: @(#)winmenu.c 3.1 92/3/7
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
/*
* File for creating menus.
*
* + Global functions: start_menu, add_menu, end_menu, select_menu
*/
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/List.h>
#include <X11/Xaw/Viewport.h>
#include <X11/Xaw/Cardinals.h>
#include "hack.h"
#include "winX.h"
static void clear_old_menu();
static char *copy_of();
#define check_menu(func_name) \
{ \
if (!menu_info->is_menu) { \
impossible("%s: called before start_menu", func_name); \
return; \
} \
}
static char menu_selected; /* selected menu item */
static const char menu_translations[] =
"#override\n\
<Key>: menu_key()";
/*
* Menu callback.
*/
/* ARGSUSED */
static void
menu_select(w, client_data, call_data)
Widget w;
XtPointer client_data, call_data;
{
XawListReturnStruct *lrs = (XawListReturnStruct *) call_data;
int i;
struct menu_info_t *menu_info;
struct menu_item *curr;
struct xwindow *wp;
wp = find_widget(w);
menu_info = wp->menu_information;
for (i = 0, curr = menu_info->base; i < lrs->list_index; i++) {
if (!curr) panic("menu_select: out of menu items!");
curr = curr->next;
}
/* If we don't have a selector, try again. */
if (!curr->selector) {
XawListUnhighlight(w); /* unhilight non-menu item */
X11_nhbell();
return;
}
menu_selected = curr->selector;
nh_XtPopdown(wp->popup); /* this removes the event grab */
exit_x_event = TRUE; /* exit our event handler */
}
/*
* Called when we get a key press event on a menu window.
*/
/* ARGSUSED */
void
menu_key(w, event, params, num_params)
Widget w;
XEvent *event;
String *params;
Cardinal *num_params;
{
struct menu_info_t *menu_info;
struct menu_item *curr;
struct xwindow *wp;
char ch;
int count;
wp = find_widget(w);
menu_info = wp->menu_information;
ch = key_event_to_char((XKeyEvent *) event);
if (ch == '\0') { /* don't accept nul char/modifier event */
/* don't beep */
return;
}
for (count = 0, curr = menu_info->base; curr; curr = curr->next, count++)
if (curr->selector == ch) break;
if (curr) {
XawListHighlight(w, count); /* highlit item */
menu_selected = ch;
} else if (menu_info->other_valid && index(menu_info->other_valid, ch)) {
menu_selected = menu_info->other_response;
} else {
X11_nhbell(); /* no match */
return;
}
nh_XtPopdown(wp->popup); /* this removes the event grab */
exit_x_event = TRUE; /* exit our event handler */
}
/* Global functions ======================================================== */
void
X11_start_menu(window)
winid window;
{
struct xwindow *wp;
check_winid(window);
wp = &window_list[window];
if (wp->menu_information->is_menu) {
/* clear old menu and widgets (if any) */
clear_old_menu(wp);
} else {
wp->menu_information->is_menu = TRUE;
}
}
void
X11_add_menu(window, ch, attr, str)
winid window;
char ch;
int attr;
const char *str;
{
struct menu_item *item;
struct menu_info_t *menu_info;
check_winid(window);
menu_info = window_list[window].menu_information;
check_menu("add_menu");
item = (struct menu_item *) alloc((unsigned)sizeof(struct menu_item));
item->next = (struct menu_item *) 0;
item->selector = ch;
item->attr = attr;
item->str = copy_of(str);
if (menu_info->last) {
menu_info->last->next = item;
} else {
menu_info->base = item;
}
menu_info->last = item;
menu_info->count++;
}
void
X11_end_menu(window, cancel_ch, cancel_str, morestr)
winid window;
char cancel_ch;
const char *cancel_str;
const char *morestr;
{
struct menu_info_t *menu_info;
check_winid(window);
menu_info = window_list[window].menu_information;
check_menu("end_menu");
if(morestr && strlen(morestr))
X11_add_menu(window, 0, 0, morestr);
menu_info->other_valid = cancel_str;
menu_info->other_response = cancel_ch;
menu_info->query = morestr;
}
char
X11_select_menu(window)
winid window;
{
struct menu_item *curr;
struct xwindow *wp;
struct menu_info_t *menu_info;
Arg args[8];
Cardinal num_args;
String *ptr;
int i;
Widget viewport_widget;
Dimension pixel_height, top_margin, spacing;
XFontStruct *fs;
check_winid(window);
wp = &window_list[window];
menu_info = wp->menu_information;
#if defined(LINT) || defined(GCC_WARN)
{
/* cannot use check_menu, since it doesn't return anything */
if (!menu_info->is_menu) {
impossible("%s: called before start_menu", "select_menu");
return '\0';
}
}
#else
check_menu("select_menu");
#endif
#ifdef VERBOSE
/* ********** */
if (menu_info->other_valid) {
char *cp;
printf("select_menu: other_valid = \"");
for (cp = menu_info->other_valid; *cp; cp++) {
if (*cp < 32) {
printf("^%c", '@' + *cp);
} else
printf("%c", *cp);
}
printf("\"\n");
} else {
printf("select_menu: other_valid = NULL\n");
}
if (menu_info->other_response < 32) {
printf("select_menu: other_response = '^%c'\n",
'@' + menu_info->other_response);
} else {
printf("select_menu: other_response = '%c'\n",
menu_info->other_response);
}
if (menu_info->query) {
printf("select_menu: query = \"%s\"\n", menu_info->query);
} else {
printf("select_menu: query = NULL\n");
}
/* ********** */
#endif
num_args = 0;
XtSetArg(args[num_args], XtNallowShellResize, True); num_args++;
wp->popup = XtCreatePopupShell("menu", transientShellWidgetClass,
toplevel, args, num_args);
menu_info->list_pointer =
(String *) alloc((unsigned) (sizeof(String) * (menu_info->count+1)));
for (i = 0, ptr = menu_info->list_pointer, curr = menu_info->base;
i < menu_info->count; i++, ptr++, curr = curr->next) {
*ptr = (String) curr->str;
}
*ptr = (String) 0;
num_args = 0;
XtSetArg(args[num_args], XtNallowVert, True); num_args++;
viewport_widget = XtCreateManagedWidget(
"menu_viewport", /* name */
viewportWidgetClass,
wp->popup, /* parent widget */
args, num_args); /* values, and number of values */
num_args = 0;
XtSetArg(args[num_args], XtNforceColumns, True); num_args++;
XtSetArg(args[num_args], XtNdefaultColumns, 1); num_args++;
XtSetArg(args[num_args], XtNlist, menu_info->list_pointer); num_args++;
XtSetArg(args[num_args], XtNtranslations,
XtParseTranslationTable(menu_translations)); num_args++;
wp->w = XtCreateManagedWidget(
"menu_list", /* name */
listWidgetClass,
viewport_widget, /* parent widget */
args, /* set some values */
num_args); /* number of values to set */
XtAddCallback(wp->w, XtNcallback, menu_select, (XtPointer) 0);
menu_info->valid_widgets = TRUE;
/* Get the font and margin information. */
num_args = 0;
XtSetArg(args[num_args], XtNfont, &fs); num_args++;
XtSetArg(args[num_args], XtNinternalHeight, &top_margin); num_args++;
XtSetArg(args[num_args], XtNrowSpacing, &spacing); num_args++;
XtGetValues(wp->w, args, num_args);
/* font height is ascent + descent */
pixel_height = top_margin +
((menu_info->count + 4) *
(fs->max_bounds.ascent + fs->max_bounds.descent + spacing));
/* if viewport will be bigger than the screen, limit its height */
if ((Dimension) XtScreen(wp->w)->height <= pixel_height) {
pixel_height = XtScreen(wp->w)->height / 2;
num_args = 0;
XtSetArg(args[num_args], XtNheight, pixel_height); num_args++;
XtSetValues(viewport_widget, args, num_args);
}
XtRealizeWidget(wp->popup); /* need to realize before we position */
positionpopup(wp->popup);
menu_selected = '\0';
nh_XtPopup(wp->popup, XtGrabExclusive, wp->w);
(void) x_event(EXIT_ON_EXIT);
return menu_selected;
}
/* End global functions ==================================================== */
static char *
copy_of(s)
char *s;
{
char *copy;
if (s) {
copy = (char *) alloc((unsigned) (strlen(s)+1));
Strcpy(copy,s);
} else {
copy = (char *) alloc((unsigned) 1);
*copy = '\0';
}
return copy;
}
static void
clear_old_menu(wp)
struct xwindow *wp;
{
struct menu_info_t *menu_info = wp->menu_information;
while (menu_info->base) {
menu_info->last = menu_info->base;
menu_info->base = menu_info->base->next;
free(menu_info->last->str);
free((char *)menu_info->last);
}
menu_info->last = (struct menu_item *) 0;
menu_info->other_valid = (char *) 0;
menu_info->other_response = '\0';
menu_info->query = (char *) 0;
menu_info->count = 0;
if (menu_info->valid_widgets) {
nh_XtPopdown(wp->popup);
XtDestroyWidget(wp->popup);
menu_info->valid_widgets = FALSE;
free((char *) menu_info->list_pointer);
}
}
void
create_menu_window(wp)
struct xwindow *wp;
{
struct menu_info_t *menu_info;
wp->type = NHW_MENU;
wp->menu_information = menu_info =
(struct menu_info_t *) alloc(sizeof(struct menu_info_t));
menu_info->base = (struct menu_item *) 0;
menu_info->last = (struct menu_item *) 0;
menu_info->query = (char *) 0;
menu_info->other_valid = (char *) 0;
menu_info->other_response = '\0';
menu_info->count = 0;
menu_info->list_pointer = (String *) 0;
menu_info->valid_widgets = FALSE;
wp->w = wp->popup = (Widget) 0;
menu_info->is_menu = FALSE;
}
void
destroy_menu_window(wp)
struct xwindow *wp;
{
/* printf("destroy_menu_window\n"); */
clear_old_menu(wp); /* this will also destroy the widgets */
free((char *) wp->menu_information);
wp->type = NHW_NONE; /* allow re-use */
}